package com.enterprise.support.utility;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;
import org.apache.log4j.Logger;

import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

import static java.net.URLEncoder.encode;

/**
 * Created by IntelliJ IDEA.
 * User: Zhanggaojiang
 * Date: 11-1-19
 * Time: 上午10:43
 * Email: z82422@gmail.com
 * Web层辅助对象
 */
public class WebUtility {
    private static Logger logger = Logger.getLogger(Logger.class);
    public static String WEB_SESSION_SHOW_MSG_BOX_KEY = "web_session_show_msg_box_key";
    public static String KEY_UPLOADER_PROGRESS = "key_uploader_progress";
    private static DiskFileItemFactory factory = new DiskFileItemFactory();

    static {
        try {
            // Set File Uploader factory constraints
            //(1024 * 1024) * 10
            factory.setSizeThreshold((1024 * 1024) * Configuration.get().getInt("web_fileuploader_sizethreshold"));
            factory.setRepository(FileUtility.TEMP_DIRECTORY);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 强制 IE 不缓存
     */
    public static void notCache(HttpServletResponse response) {
        response.setContentType("text/html; charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Expires", "0");
        response.setDateHeader("Expires", 0);
    }

    /**
     * 强制 IE 缓存
     */
    public static void Cache(HttpServletResponse response, int minutes) {
        response.setContentType("text/html; charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.addHeader("Cache-Control", "max-age=" + (1000 * 60 * minutes));
    }

    /**
     * 是否POST请求
     *
     * @param request
     * @return
     */
    public static boolean isPostRequest(HttpServletRequest request) {
        return request.getMethod().equalsIgnoreCase("POST");
    }

    public static boolean isPostRequest() {
        HttpServletRequest request = ActionContext.getContext().getRequest();
        return request.getMethod().equalsIgnoreCase("POST");
    }

    /**
     * 是否Get请求
     *
     * @param request
     * @return
     */
    public static boolean isGetRequest(HttpServletRequest request) {
        return request.getMethod().equalsIgnoreCase("GET");
    }

    public static boolean isGetRequest() {
        HttpServletRequest request = ActionContext.getContext().getRequest();
        return request.getMethod().equalsIgnoreCase("GET");
    }


    public static boolean isFullUrl(String link) {
        if (link == null) {
            return false;
        }
        link = link.trim().toLowerCase();
        return link.startsWith("http://") || link.startsWith("https://") || link.startsWith("file://");
    }

    public static String fullUrl(String pageUrl, String link) {
        if (isFullUrl(link)) {
            return link;
        } else if (link != null && link.startsWith("?")) {
            int qindex = pageUrl.indexOf('?');
            int len = pageUrl.length();
            if (qindex < 0) {
                return pageUrl + link;
            } else if (len > qindex + 1) {
                return pageUrl.substring(0, qindex) + link;

            } else if (qindex == len - 1) {
                return pageUrl.substring(0, len - 1) + link;
            } else {
                return pageUrl + "&" + link.substring(1);
            }
        }

        boolean isLinkAbsolute = link.startsWith("/");
        if (!isFullUrl(pageUrl)) {
            pageUrl = "http://" + pageUrl;
        }

        int slashIndex = isLinkAbsolute ? pageUrl.indexOf("/", 8) : pageUrl.lastIndexOf("/");
        if (slashIndex <= 8) {
            pageUrl += "/";
        } else {
            pageUrl = pageUrl.substring(0, slashIndex + 1);
        }

        return isLinkAbsolute ? pageUrl + link.substring(1) : pageUrl + link;
    }


    public static String replacelink(String content, String link) {
        return content.replaceAll("(<a[^<>]+(51cto.com)+[^<>]+>(.+)</a>)", "1");
        //+[^<>]+>(.+)
    }

    public static String replace(String content, String regex, String value) {
        return content.replaceAll(regex, value);
    }


    /**
     * 封装 转换Request 为 Enterprise DATA
     *
     * @return
     */
    public static Enterprise getInput() {
        HttpServletRequest request = ActionContext.getContext().getRequest();
        return getInput(request);
    }

    public static HttpServletRequest getRequest() {
        return ActionContext.getContext().getRequest();
    }

    public static HttpSession getSession() {
        return ActionContext.getContext().getSession();
    }

    public static ServletContext getServletContext() {
        return ActionContext.getContext().getServletContext();
    }

    /**
     * 封装 转换Request 为 Enterprise DATA
     *
     * @param request
     * @return
     */
    public static Enterprise getInput(HttpServletRequest request) {
        Enterprise entity = new Enterprise("REQUEST_DATA");
        final HttpSession session = request.getSession(true);
        ServletRequestContext servletResultContext = new ServletRequestContext(request);
        for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) {
            String key = (String) e.nextElement();
            String[] values = request.getParameterValues(key);
            for (String value : values) {
                if (entity.containsKey(key) && !key.equalsIgnoreCase("id")) {
                    Object temp = entity.get(key);
                    if (temp instanceof List) {
                        ((List) temp).add(value);
                    } else {
                        List temps = new ArrayList();
                        temps.add(temp);
                        temps.add(value);
                        entity.put(key, temps);
                    }
                } else {
                    entity.put(key, value);
                }
            }
        }
        if (ServletFileUpload.isMultipartContent(servletResultContext)) {
            try {
                ServletFileUpload fileupload = new ServletFileUpload(factory);
                fileupload.setSizeMax(Long.valueOf((1024 * 1024) * Configuration.get().getLong("web_fileuploader_maxsize")));
                fileupload.setHeaderEncoding(Configuration.get().getString("web_input_charset"));
                fileupload.setProgressListener(new ProgressListener() {
                    public void update(long read, long length, int i) {
                        Enterprise progress = (Enterprise) session.getAttribute(KEY_UPLOADER_PROGRESS);
                        if (null == progress) {
                            progress = new Enterprise("UploaderProgress");
                            session.setAttribute(KEY_UPLOADER_PROGRESS, progress);
                        }
                        progress.set("read", read);
                        progress.set("length", length);
                        BigDecimal readDecimal = new BigDecimal(read);
                        BigDecimal lengthDecimal = new BigDecimal(length);
                        BigDecimal percent = new BigDecimal(100);
                        progress.set("percent", length == read ? 100 : readDecimal.divide(lengthDecimal, 4, BigDecimal.ROUND_HALF_UP).multiply(percent).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                });
                List<FileItem> fileItem = fileupload.parseRequest(servletResultContext);
                for (FileItem field : fileItem) {
                    if (!field.isFormField() || !Validation.isEmpty(field.getString()))
                        if (entity.containsKey(field.getFieldName())) {
                            Object temp = entity.get(field.getFieldName());
                            if (temp instanceof List) {
                                ((List) temp).add(field.isFormField() ? field.getString(Configuration.get().getString("web_input_charset")) : field);
                            } else {
                                List temps = new ArrayList();
                                temps.add(temp);
                                temps.add(field.isFormField() ? field.getString(Configuration.get().getString("web_input_charset")) : field);
                                entity.put(field.getFieldName(), temps);
                            }
                        } else {
                            entity.put(field.getFieldName(), field.isFormField() ? field.getString(Configuration.get().getString("web_input_charset")) : field);
                        }
                }
            } catch (Exception ex) {
                System.err.println("上传文件读取内容异常:" + ex.getMessage());
                ex.printStackTrace();
            }
        }
        return entity;
    }

    public static String appendURL(Map<String, String> temps, String action) {
        try {
            StringBuffer strBuffer = new StringBuffer();
            Map<String, Object> parms = (ActionContext.getContext() == null) ? Collections.<String, Object>emptyMap() : getInput(ActionContext.getContext().getRequest());
            for (String key : parms.keySet()) {
                if (!temps.containsKey(key) && !key.equalsIgnoreCase("enterprise_page_index")) {
                    if (!Validation.isEmpty(strBuffer.toString())) {
                        strBuffer.append("&");
                    }
                    strBuffer.append(key).append("=").append(parms.get(key).toString());
                }
            }
            if (!temps.keySet().isEmpty()) {
                for (String key : temps.keySet()) {
                    if (!Validation.isEmpty(strBuffer.toString())) {
                        strBuffer.append("&");
                    }
                    strBuffer.append(key).append("=").append(temps.get(key).toString());
                }
            }
            if (!Validation.isEmpty(strBuffer)) {
                return action + "?" + strBuffer.toString();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return action;
    }

    /**
     * 获取Cookie 信息
     *
     * @param
     * @return
     */
    public static Enterprise getCookies() {
        Enterprise input = new Enterprise();
        Cookie[] cookies = ActionContext.getContext().getRequest().getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                try {
                    input.set(cookie.getName(), java.net.URLDecoder.decode(cookie.getValue(), "UTF-8"));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return input;
    }

    /**
     * 设置Cookie 信息
     *
     * @param
     * @return
     */
    public static void setCookies(Enterprise input) {
        HttpServletResponse response = ActionContext.getContext().getResponse();
        if (response != null) {
            for (String key : (Set<String>) input.keySet()) {
                if (!key.equalsIgnoreCase("timeout")) {
                    try {
                        Cookie cookie = new Cookie(key, encode(input.isEmpty(key) ? "" : input.getString(key), "utf-8"));
                        if (!input.isEmpty("timeout")) {
                            cookie.setMaxAge(input.getInt("timeout"));
                        } else {
                            cookie.setMaxAge(Configuration.get().getInt("web_info_in_cookie.timeout"));
                        }
                        cookie.setPath(Configuration.get().getString("web_info_in_cookie.path"));
                        cookie.setDomain(Configuration.get().getString("web_info_in_cookie.domain"));
                        response.addCookie(cookie);
                    } catch (Exception ex) {
                        logger.error("写入Cookie异常,key=" + key + ",完整参数:" + input, ex);
                    }
                }
            }
        }
    }

    /**
     * 获取绝对路径
     *
     * @param path
     */
    public static String getAbsolutePath(String path) {
        HttpServletRequest request = ActionContext.getContext().getRequest();
        StringBuffer absolutePath = new StringBuffer();
        absolutePath.append(request.getContextPath()).append(path);
        return absolutePath.toString();

    }

    /**
     * URL 编码
     *
     * @return
     */
    public static String getURLEncoder(String url) {
        try {
            return URLEncoder.encode(url, "utf-8");
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return url;
    }

    /**
     * URL 解码
     *
     * @param url
     * @return
     */
    public static String getURLDecoder(String url) {
        try {
            return URLDecoder.decode(url, "utf-8");
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        }
        return url;
    }

    public static void showMsgBox(String message) {
        HttpSession session = ActionContext.getContext().getSession();
        session.setAttribute(WEB_SESSION_SHOW_MSG_BOX_KEY, new WebMessageBox(message));
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
